package com.example.fast.web.aop;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

import static com.example.fast.common.util.ExceptionUtils.exceptionSimpleDesc;
import static com.example.fast.common.util.ExceptionUtils.unwrapThrowable;

/**
 * Controller层访问记录，方便开发时使用
 */
@Slf4j
//@Profile({"dev"})
@Aspect
@Order(-2)
@Component
public class ControllerLogAspect {

    @Pointcut("execution(public com.example.fast.common.util.R com.example.fast.web.controller.*.*(..))")
    public void log() {
    }

    @Before("log()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            log.warn("ServletRequestAttributes null.");
            return;
        }
        HttpServletRequest request = attributes.getRequest();

        log.info("前端请求 -> [{}], uri: {}, params: {}", request.getMethod(), request.getRequestURI(),
                JSON.toJSONString(joinPoint.getArgs(), SerializerFeature.IgnoreNonFieldGetter));
    }

    @AfterReturning(pointcut = "log()", returning = "object")
    public void doAfterReturning(Object object) {
        log.info("响应返回 -> {}", JSON.toJSONString(object, SerializerFeature.IgnoreNonFieldGetter));
    }

    @AfterThrowing(pointcut = "log()", throwing = "ex")
    public void afterThrowing(Throwable ex) {
        log.info("响应异常 -> {}", exceptionSimpleDesc(unwrapThrowable(ex)));
    }
}